package com.acme.bankapp.domain.bank;

import java.io.*;
import java.util.*;

import com.acme.bankapp.domain.exception.*;
import com.acme.bankapp.service.listener.*;

/**
 * Class stores clients of the bank
 * @author alex
 */
@SuppressWarnings("serial")
public class Bank implements Serializable {
	private Client[] clients;
	private int clientsCount;
	private int clientsCurrent;
	private static final int CLIENTS_MAX = 10;
	
	private ClientRegistrationListener[] listeners;
	private int listenersCount;
	private static final int LISTENERS_MAX = 10;
	
	/**
	 * The default constructor
	 * @throws ListenersMaxException 
	 */
	public Bank() throws ListenersMaxException {
		this.clients = new Client[Bank.CLIENTS_MAX];
		this.listeners = new ClientRegistrationListener[Bank.LISTENERS_MAX];
		
		this.addListener(new ClientRegistrationListener() {
			public void onClientAdded(Client client) {
				System.out.println("* " + client.getName() + " " + new Date());
			}
		});
	}
	
	/**
	 * @param client the client
	 * @return the client
	 */
	public Client getClient(Client client) {
		for (int i = 0; i < this.clientsCount; i++) {
			if (this.clients[i].equals(client)) {
				return this.clients[i];
			}
		}
		return null;
	}
	
	/**
	 * @param client the client
	 * @throws ClientsMaxException 
	 * @throws ClientExistsException 
	 */
	public void addClient(Client client) throws ClientsMaxException, ClientExistsException {
		if (this.clientsCount < Bank.CLIENTS_MAX) {
			if (this.getClient(client) == null) {
				this.clients[this.clientsCount++] = client;
				this.runListeners(client);
			} else {
				throw new ClientExistsException();
			}
		} else {
			throw new ClientsMaxException();
		}
	}
	
	/**
	 * @return whether iterator has next client
	 */
	public boolean hasNextClient() {
		if (this.clientsCurrent < this.clientsCount) {
			return true;
		} else {
			this.clientsCurrent = 0;
			return false;
		}
	}
	
	/**
	 * @return iterator next client
	 */
	public Client getNextClient() {
		return this.clients[this.clientsCurrent++];
	}
	
	/**
	 * @return the clients count
	 */
	public int getClientsCount() {
		return this.clientsCount;
	}
	
	/**
	 * @param listener the listener
	 * @throws ListenersMaxException 
	 */
	public void addListener(ClientRegistrationListener listener) throws ListenersMaxException {
		if (this.listenersCount < Bank.LISTENERS_MAX) {
			this.listeners[this.listenersCount++] = listener;
		} else {
			throw new ListenersMaxException();
		}
	}
	
	/**
	 * Method iterates and runs listeners
	 * @param client the client
	 */
	public void runListeners(Client client) {
		for (int i = 0; i < this.listenersCount; i++) {
			this.listeners[i].onClientAdded(client);
		}
	}
}
